package com.bestv.search.management.servlet;

import com.bestv.search.common.cache.SiteCache;
import com.bestv.search.common.cache.SystemCache;
import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.SysRole;
import com.bestv.search.common.model.SysUser;
import com.bestv.search.common.service.SiteManager;
import com.bestv.search.common.service.SysUserManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.*;

public final class DispatchServlet extends HttpServlet implements Servlet {

    private static final long serialVersionUID = -3977773632252993190L;
    protected final Log log = LogFactory.getLog(getClass());
    private WebApplicationContext wac;
    private SysUserManager userManager;
    private SystemCache systemCache;

    public DispatchServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doExecute(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doExecute(request, response);
    }

    public void init() throws ServletException {
        ServletContext application = getServletContext();
        wac = WebApplicationContextUtils.getWebApplicationContext(application);
        userManager = (SysUserManager) wac.getBean("userManager");
        systemCache = (SystemCache) wac.getBean("systemCache");
        Object siteManager = wac.getBean("siteManager");
        DataSourceKey key = DataSourceKeyUtil.convert(systemCache.getLocalDataSourceKey());
        SiteCache.initMap(key, (SiteManager) siteManager);
        super.init();
    }

    private void doExecute(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        HttpSession session = request.getSession();
        String loginName = (String) session.getAttribute("ACEGI_SECURITY_LAST_USERNAME");
        String result;
        String cmd = request.getParameter("cmd");
        String action = request.getParameter("action");
        String ulf = request.getParameter("ulf");
        String expExcelFlag = request.getParameter("expExcel");

        // Set local data source key to session as default data source key, if
        // dataSourceKey is null.
        String dataSourceKey = (String) session.getAttribute("dataSourceKey");
        if (dataSourceKey == null || dataSourceKey.equals("")) {
            dataSourceKey = systemCache.getLocalDataSourceKey();
            session.setAttribute("dataSourceKey", dataSourceKey);
        }

        // update DataSourceKey
        if (cmd == null && action.equalsIgnoreCase("setDataSourceKey")) {
            session.setAttribute("dataSourceKey", request.getParameter("dataSourceKey"));
            return;
        }

        // get DataSourceKey
        if (cmd == null && action.equalsIgnoreCase("getDataSourceKey")) {
            response.getWriter().write(dataSourceKey);
            return;
        }

        // get local DataSourceKey
        if (cmd == null && action.equalsIgnoreCase("getLocalDataSourceKey")) {
            response.getWriter().write(systemCache.getLocalDataSourceKey());
            return;
        }

        // Gets data Source key
        DataSourceKey dsKey = DataSourceKeyUtil.convert(dataSourceKey);

        HSSFWorkbook wbook = null;

        log.debug("cmd:" + cmd);
        log.debug("action:" + action);
        if (loginName == null || "".equals(loginName)) {
            result = "[null]";
        } else {
            SysUser user = userManager.getUserByLoginName(dsKey, loginName);
            // If isn't HDQ user, just can access the site that user belong to,
            if (user != null) {
                if (user.getSite().getCode() != null) {
                    // Check Permission
                    Set<SysRole> roles = user.getRoles();
                    boolean permissionFlag = false;
                    for (SysRole role : roles) {
                        if (role != null
                                && (role.getName().equals(systemCache.getLocalDataSourceKey()) || role.getName()
                                .equals("HDQ"))) {
                            permissionFlag = true;
                            break;
                        }
                    }

                    // don have Permission
                    if (!permissionFlag) {
                        response.getWriter().write("No Permission");
                        return;
                    }
                }
            }

            if ("currentUser".equals(cmd)) {
                if (user == null)
                    result = "[null]";
                else {
                    try {
                        List<JSONObject> roles = new ArrayList<JSONObject>();
                        Iterator<SysRole> iterator = user.getRoles().iterator();
                        while (iterator.hasNext()) {
                            SysRole role = iterator.next();
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("id", role.getId());
                            jsonObject.put("name", role.getName());
                            jsonObject.put("description", role.getDescription());
                            roles.add(jsonObject);
                        }
                        JSONArray jsonArray = new JSONArray(roles.toArray());
                        result = "{'username':'" + user.getUsername() + ":" + user.getSite().getName() + "','sc':'"
                                + user.getSite().getCode() + "','roles':" + jsonArray.toString() + "}";
                    } catch (JSONException e) {
                        log.error(e);
                        e.printStackTrace();
                        result = "[error]";
                    }
                }
            } else {
                // get current user object
                if (user == null) {
                    result = "[null]";
                } else {
                    Object command = wac.getBean(cmd);
                    try {
                        if (expExcelFlag != null && "y".equals(expExcelFlag)) {
                            Method method = command.getClass().getDeclaredMethod(action,
                                    new Class[]{SysUser.class, Map.class, DataSourceKey.class});
                            wbook = (HSSFWorkbook) method.invoke(command, user, request.getParameterMap(), dsKey);
                            result = "scuuess";
                        } else {
                            if (!"y".equals(ulf)) {
                                Method method = command.getClass().getDeclaredMethod(action,
                                        new Class[]{SysUser.class, Map.class, DataSourceKey.class});
                                result = (String) method.invoke(command, user, request.getParameterMap(), dsKey);
                            } else {
                                Method method = command.getClass().getDeclaredMethod(action,
                                        new Class[]{SysUser.class, HttpServletRequest.class, DataSourceKey.class});
                                result = (String) method.invoke(command, user, request, dsKey);
                            }
                        }
                    } catch (Exception e) {
                        log.error(e);
                        e.printStackTrace();
                        result = "[error]";
                    }
                }
            }
        }

        // save excel by response
        if (expExcelFlag != null && "y".equals(expExcelFlag) && "scuuess".equals(result) && wbook != null) {
            response.reset();
            response.setContentType("application/msexcel;charset=UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=\"Excel1.xls\"");

            OutputStream out = response.getOutputStream();
            try {
                wbook.write(out);
                out.flush();
            } catch (Exception e) {
                log.error("Export excel failed @" + new Date());
                e.printStackTrace();
            } finally {
                if (out != null)
                    out.close();
            }
        } else {
            response.getWriter().write(result);
        }
    }
}